# _*_coding:utf-8_*_
from ATS.instrumentDriver.Oscilloscpoe import DSO_X_2022A as ScopeDrive
from ATS.instrumentDriver.IVGeneralFunc import IVGeneralFunc_B2900A as IVFunc
from ATS.util import mathlib as MathLib
from ATS.datamanager.DataManager import DataManager
import time


def Scope_TEST(source, n):
    start = time.clock()
    print("source dict is:", source)

    is_manual = DataManager().getgdata("Manual_Run")
    raw_data = PIN_general(source, n)

    if is_manual:
        print('is_manual_TEST')
    else:
        data_global = DataManager().getgdata("RAW_DATA")
        if data_global is None:
            data_global = {}
        data_global.update(raw_data)
        DataManager().addgdata("RAW_DATA", data_global)

    print(time.clock() - start)
    return


def PIN_general(source, n):
    """
    rval = IVFunc.srcmeas(sweep, step, bias, open, meas_range, src_range, compliance, remote_sense,\
                         meas_seq, meas_pro, common_ext)
    """
    global raw_data
    rval = ScopeDrive.srcmeas(source, n)
    print('PIN_general rval', rval)
    if rval:
        raw_data = {"Vpp": rval['DSO1']["Vpp"], "RiseTime": rval['DSO1']["RiseTime"],
                    "FallTime": rval['DSO1']["FallTime"]}
        __postdata("V", raw_data["Vpp"])
        # print('raw_data["Vpp"]',raw_data["Vpp"])
        __postdata("R", raw_data["RiseTime"])
        # print('raw_data["RiseTime"]',raw_data["RiseTime"])
        __postdata("F", raw_data["FallTime"])
        # print('raw_data["FallTime"]',raw_data["FallTime"])
    return raw_data


def PIN_FVMI_alg1(source, src_range, meas_range, compliance, meas_seq, common, smu_use):
    print("PIN_FVMI_alg1(source,src_range, meas_range,compliance,meas_seq, common, smu_use):")
    """
    algorithm = 1
    src_range = {'SMU1': [u'Best Fixed', 100, 1]}
    compliance = {'SMU1': [0.1, 0]}
    source = {'SMU1': [[0, 10, 100], 1]}
    meas_seq = {'SMU1': [2, ['V', 'I']]}
    common = {'NPLC': 1, 'swp_pts': 2, 'delay_time': 0}
    spec = {'r_low': 0, 'i1_hi': 1, 'vbr_low': 0, 'v1': 400, 'vr': 100, 'r_hi': 1, 'vbr_hi': 1, 'i1_low': 0, 'ibr': 1}
    meas_range = {'SMU1': [u'Auto', 1e-06, 0]}
    """
    sweep = {}
    step = {}
    bias = {}
    bias[smu_use] = [source[smu_use][0][1], source[smu_use][1]]
    open = {}
    remote_sense = {}
    from ATS.application.PIN_APD_App.PIN import INIT_MEASRNG
    meas_range_1 = {smu_use: [1, INIT_MEASRNG, 0]}
    # Meas_Pro = {use_SMU:["V"]}
    meas_pro = {}
    common_ext = {"loop_mode": 1, "is_postdata": 0, "is_returndata": 1, "gs_flag": 0,
                  "avg_num": 1, "sample_pts": 1, "time_stamp": 0, "stop_comp": 0, "hold_time": 0,
                  "step_pts": 1, "off_0V": 1}
    common_ext.update(common)
    rval = IVFunc.setup(sweep, step, bias, open, meas_range_1, src_range, compliance, remote_sense,
                        meas_seq, meas_pro, common_ext)
    # print(time.clock()-start)
    if rval < 0:
        return reporterror("Reverse IV sweepping failed.", rval)
    rval = IVFunc.srcmeas(sweep, step, bias, open, meas_range_1, src_range, compliance, remote_sense,
                          meas_seq, meas_pro, common_ext)
    raw_data = {"V_FVMI": rval[smu_use]["V"], "I_FVMI": rval[smu_use]["I"]}
    bias[smu_use][0] = source[smu_use][0][2]
    meas_range_2 = meas_range
    rval = IVFunc.setup(sweep, step, bias, open, meas_range_2, src_range, compliance, remote_sense,
                        meas_seq, meas_pro, common_ext)
    # print(time.clock()-start)
    rval = IVFunc.srcmeas(sweep, step, bias, open, meas_range_2, src_range, compliance, remote_sense,
                          meas_seq, meas_pro, common_ext)
    raw_data["V_FVMI"].append(rval[smu_use]["V"][0])
    raw_data["I_FVMI"].append(rval[smu_use]["I"][0])
    raw_data["R_FVMI"] = [v / raw_data["I_FVMI"][ind] for ind, v in enumerate(raw_data["V_FVMI"])]
    __postdata("V", raw_data["V_FVMI"])
    __postdata("I", raw_data["I_FVMI"])
    __postdata("R", raw_data["R_FVMI"])

    return raw_data


def reporterror(msg, err_code):
    # print("********* reporterror",msg)
    DataManager().posterror(msg)
    return err_code


def __postdata(name, val):
    print('__postdata', name, val)
    if isinstance(val, type([])):
        DataManager().postarraydata(name, val)
    else:
        DataManager().postSingleData(name, val)


def update_k(org, old_k, new_k):
    if new_k not in org:
        org[new_k] = org[old_k]
        del org[old_k]
    return org


def key_convert(type_code, words):
    if type_code == "rng_mode":
        if words == "Limited Auto":
            return 2
        elif words == "Fixed":
            return 1
        elif words == "Auto":
            return 0
        elif words == "Best Fixed":
            return 1


def calc_judge_alg0(raw_data, spec, result):
    iv_flag = DataManager().getgdata("IV_FLAG")
    calc_i1 = DataManager().getgdata("CALC_I1")
    # print(raw_data, spec)
    if iv_flag == 1:
        v_val = raw_data["V_FVMI"]
        i_val = raw_data["I_FVMI"]
        r_val = raw_data["R_FVMI"]
    else:
        v_val = raw_data["V_FIMV"]
        i_val = raw_data["I_FIMV"]
        r_val = raw_data["R_FIMV"]
    if spec.get("v1") is not None and spec.get("i1_hi") is not None and spec.get("i1_low") is not None and calc_i1:
        pos_V1 = MathLib.FINDLIN(v_val, spec["v1"], 0)
        result["I1_V1"] = MathLib.AT(i_val, pos_V1)
        result["V1"] = spec["v1"]
        if result["I1_V1"] > spec["i1_hi"] or result["I1_V1"] < spec["i1_low"]:
            result["I1_PorF"] = 0
    else:
        result.pop("I1_PorF")
    if spec.get("ibr") is not None and spec.get("vbr_hi") is not None and spec.get("vbr_low") is not None:
        max_i_val = max(MathLib.ABS(i_val))
        if abs(spec["ibr"]) >= max_i_val:
            result["Vbr_Ibr"] = v_val[-1]
        else:
            pos_Ibr = MathLib.FINDLIN(i_val, spec["ibr"], 0)
            result["Vbr_Ibr"] = MathLib.AT(v_val, pos_Ibr)
        result["Ibr"] = spec["ibr"]
        if result["Vbr_Ibr"] > spec["vbr_hi"] or result["Vbr_Ibr"] < spec["vbr_low"]:
            result["Vbr_PorF"] = 0
    else:
        result.pop("Vbr_PorF")
    if iv_flag == 1:
        if spec.get("vr") is not None and spec.get("r_hi") is not None and spec.get("r_low") is not None:
            pos_Vr = MathLib.FINDLIN(v_val, spec["vr"], 0)
            result["R_Vr"] = MathLib.AT(r_val, pos_Vr)
            result["Vr"] = spec["vr"]
            if result["R_Vr"] > spec["r_hi"] or result["R_Vr"] < spec["r_low"]:
                result["R_PorF"] = 0
        else:
            result.pop("R_PorF")
    else:
        if spec.get("ir") is not None and spec.get("r_hi") is not None and spec.get("r_low") is not None:
            pos_Ir = MathLib.FINDLIN(i_val, spec["ir"], 0)
            result["R_Ir"] = MathLib.AT(r_val, pos_Ir)
            result["Ir"] = spec["ir"]
            if result["R_Ir"] > spec["r_hi"] or result["R_Ir"] < spec["r_low"]:
                result["R_PorF"] = 0
        else:
            result.pop("R_PorF")


def calc_judge_alg1(raw_data, spec, result):
    # error check
    if "V_FVMI" not in raw_data:
        result["R_Vr"] = -9999
        result["Vr"] = -9999
        result["I1_V1"] = -9999
        result["V1"] = -9999
        result["R_PorF"] = 0
        result["I1_PorF"] = 0
    else:
        result["R_Vr"] = raw_data["R_FVMI"][0]
        result["Vr"] = raw_data["V_FVMI"][0]
        if result["R_Vr"] > spec["r_hi"] or result["R_Vr"] < spec["r_low"]:
            result["R_PorF"] = 0
        result["I1_V1"] = raw_data["I_FVMI"][1]
        result["V1"] = raw_data["V_FVMI"][1]
        if result["I1_V1"] > spec["i1_hi"] or result["I1_V1"] < spec["i1_low"]:
            result["I1_PorF"] = 0
    if "V_FIMV" not in raw_data:
        result["Vbr_Ibr"] = -9999
        result["Ibr"] = -9999
        result["Vbr_PorF"] = 0
    else:
        result["Vbr_Ibr"] = raw_data["V_FIMV"][1]
        result["Ibr"] = raw_data["I_FIMV"][1]
        if result["Vbr_Ibr"] > spec["vbr_hi"] or result["Vbr_Ibr"] < spec["vbr_low"]:
            result["Vbr_PorF"] = 0


def calc_judge(raw_data, spec):
    """
    raw_data = {"V_FVMI":[],"I_FVMI":[],"R_FVMI":[],"V_FIMV":[],"I_FIMV":[], "R_FIMV":[]}
    spec = {"V1":400,"Ibr":0.0001, "Vr":166, "I1_Hi":0.001, "I1_Low":0,"Vbr_Hi":0.001,"Vbr_Low":0,\
            "R_Hi":150, "R_Low":100}
    spec = {"V1":400, "I1_Hi":0.001, "I1_Low":-0.001, "Ibr":0.002, "Vbr_Hi":60,  "Vbr_Low":0,\
            "Ir":0.003, "R_Hi":20,"R_Low":10}
    {'ibr': 0.01, 'ir': 0.02, 'r_low': 2, 'i1_hi': 0.01, 'vbr_low': 1, 'v1': 1, 'r_hi': 6,\
             'vbr_hi': 4, 'i1_low': -0.01}
    """
    algorithm = DataManager().getgdata("ALGORITHM")
    result = {"I1_PorF": 1, "Vbr_PorF": 1, "R_PorF": 1}

    if algorithm == 0:
        calc_judge_alg0(raw_data, spec, result)
    else:
        calc_judge_alg1(raw_data, spec, result)
    return result


def siteend_calc():
    # print("********* in siteend_calc")
    err_code = -1001
    cur_site = DataManager().getgdata("siteID")
    iv_flag = DataManager().getgdata("IV_FLAG")
    algorithm = DataManager().getgdata("ALGORITHM")
    cur_site = cur_site.lower()
    proj_setting = DataManager().getCurIni()
    crit = proj_setting["CRITERIA"]
    limit_k = None
    for k in crit:
        sites = crit[k].split(",")
        sites = [s.strip().lower() for s in sites]
        if cur_site in sites:
            limit_k = k
    if limit_k:
        if limit_k.upper() not in proj_setting:
            msg = "Cannot find out spec value (%s) for current site %s." % (limit_k.upper(), cur_site)
            reporterror(msg, err_code)
            return
    limit_k = limit_k.upper()
    raw_data = DataManager().getgdata("RAW_DATA")
    spec = proj_setting[limit_k]
    for k in spec:
        spec[k] = eval(spec[k])
    result = calc_judge(raw_data, spec)
    k_out = ["V1", "I1_V1", "Ibr", "Vbr_Ibr", "Ir", "Vr", "R_Vr", "R_Ir", "I1_PorF", "Vbr_PorF", "R_PorF"]
    for k in k_out:
        if k in result:
            __postdata(k, result[k])


if __name__ == "__main__":
    import InstCom

    InstCom.getinstconfig("online.rcf")
    print(InstCom.inst_dict)
